Skip to content

feat: add package comparison feature#383

Merged
danielroe merged 29 commits intomainfrom
feat/201
Jan 31, 2026
Merged

feat: add package comparison feature#383
danielroe merged 29 commits intomainfrom
feat/201

Conversation

@serhalp
Copy link
Member

@serhalp serhalp commented Jan 30, 2026

npmx.package.compare.demo.mp4
npmx.package.compare.demo.defer.2.mp4

Compare 2-4 packages side-by-side at /compare with facets including:

  • Performance: package size, install size, dependencies (later: total deps)
  • Health: weekly downloads, last updated, deprecation status
  • Compatibility: TypeScript types, module format, (Node.js) engines
  • Security & Compliance: license, vulnerabilities

User can select which facets to display via checkboxes, with convenient groups and quick all/none buttons per group and globally.

URL is source of truth for selected packages and facets, allowing easy sharing.

The "total install size" metric is fetched lazily after initial load and rendered initially with a loading fallback, as it is quite slow to compute.

For numeric facets, a proportional bar is shown behind the value for easy visual comparison. The greatest value in the row is used as the 100% reference.

I tried to limit subjective/opinionated highlights and such, but I did add red for Deprecated, green for no vulns, green for included types and blue for external types (seems neutral enough...), and some basic yellow/red for egregious last updated time.

Screenshot 2026-01-29 at 22 53 31 Screenshot 2026-01-29 at 23 34 37 Screenshot 2026-01-29 at 22 47 26

Add a "Compare to..." entry point on package page (keyboard shortcut: c) and a "compare" top nav item.

Screenshot 2026-01-29 at 22 52 56 Screenshot 2026-01-29 at 23 38 16

Compare 2-4 packages side-by-side at `/compare` with facets including:
- Performance: package size, install size, dependencies (later: total deps)
- Health: weekly downloads, last updated, deprecation status
- Compatibility: TypeScript types, module format, (Node.js) engines
- Security & Compliance: license, vulnerabilities

User can select which facets to display via checkboxes, with convenient groups and quick all/none
buttons per group and globally.

URL is source of truth for selected packages and facets, allowing easy sharing.

The "total install size" metric is fetched lazily after initial load and rendered initially with a
loading fallback, as it is quite slow to compute.

For numeric facets, a proportional bar is shown behind the value for easy visual comparison. The
greatest value in the row is used as the 100% reference.

I tried to limit subjective/opinionated highlights and such, but I did add red for Deprecated, green
for no vulns, green for included types and blue for external types (seems neutral enough...), and
some basic yellow/red for egregious last updated time.

Add a "Compare to..." entry point on package page (keyboard shortcut: `c`) and a "compare" top nav
item.
@vercel
Copy link

vercel bot commented Jan 30, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
npmx.dev Ready Ready Preview, Comment Jan 31, 2026 6:35pm
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
npmx-lunaria Ignored Ignored Jan 31, 2026 6:35pm
docs.npmx.dev Skipped Skipped Jan 31, 2026 6:35pm

Request Review

@github-actions
Copy link

github-actions bot commented Jan 30, 2026

Lunaria Status Overview

🌕 This pull request will trigger status changes.

Learn more

By default, every PR changing files present in the Lunaria configuration's files property will be considered and trigger status changes accordingly.

You can change this by adding one of the keywords present in the ignoreKeywords property in your Lunaria configuration file in the PR's title (ignoring all files) or by including a tracker directive in the merged commit's description.

Tracked Files

File Note
lunaria/files/en-US.json Source changed, localizations will be marked as outdated.
lunaria/files/fr-FR.json Localization changed, will be marked as complete. 🔄️
Warnings reference
Icon Description
🔄️ The source for this localization has been updated since the creation of this pull request, make sure all changes in the source have been applied.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This (and some other components) was intended to be reusable for both package comparison and foo@1.2.3 vs. foo@4.5.6 comparison, though I ended up not including the latter in this already huge PR 😅.

<!-- Category header with all/none buttons -->
<div class="flex items-center gap-2 mb-2">
<span class="text-[10px] text-fg-subtle uppercase tracking-wider">
{{ $t(`compare.facets.categories.${category}`) }}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💭 is interpolation inside a t() bad practice?

and make it a teeny bit more compact
- use the existing package search composable
- improve loading states in result grid: facet-level and column-level,
  and don't hide existing data for some columns/rows while new/others
  are loading
@danielroe
Copy link
Member

this looks amazing. there are some mobile issues - no link to the page in the menu and it overflows the page (ideally just the table would be scrollable)

I'll add a mobile menu which should help with all the content that's going in the top bar

Copy link
Member

@danielroe danielroe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

beautiful 😍

@danielroe danielroe enabled auto-merge January 31, 2026 18:37
@danielroe danielroe added this pull request to the merge queue Jan 31, 2026
Merged via the queue into main with commit 73e50ef Jan 31, 2026
16 checks passed
@danielroe danielroe deleted the feat/201 branch January 31, 2026 18:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants